package com.pai4j.aigc.llm;

import com.pai4j.common.enums.PromptTemplateEnum;
import com.pai4j.common.service.FreeMarkEngineService;
import com.pai4j.domain.vo.llm.ChatCompletionMessage;
import com.pai4j.domain.vo.llm.ChatCompletionResponse;
import com.pai4j.domain.vo.llm.ChatMessageRole;
import com.pai4j.aigc.llm.entity.LLMModelEntity;
import com.pai4j.aigc.llm.service.LLMModelService;
import com.pai4j.aigc.llm.service.LLMUsageService;
import com.pai4j.aigc.llm.service.MetricsService;
import com.pai4j.aigc.llm.service.PricingService;
import com.pai4j.aigc.llm.service.TokenEstimator;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@RefreshScope
@Service
public class LlmSummarizerService {

    @Autowired
    private FreeMarkEngineService freeMarkEngineService;

    @Value("${llm.config.model}")
    private String model;

    @Autowired
    private LLMUsageService usageService;

    @Autowired
    private TokenEstimator tokenEstimator;

    @Autowired
    private PricingService pricingService;

    @Autowired
    private MetricsService metricsService;

    @Autowired
    private LLMModelService modelService;

    public String summarize(String text) {
        try {
            Map<String, Object> vars = new HashMap<>();
            vars.put("content", text);
            vars.put("maxLen", 400);
            String prompt = freeMarkEngineService.getContentByTemplate(PromptTemplateEnum.CHAT_SUMMARY.getPath(), vars);
            AbstractLLMChatService svc = LLMServiceFactory.getLLMService(model);
            List<ChatCompletionMessage> messages = new ArrayList<>();
            messages.add(new ChatCompletionMessage(ChatMessageRole.SYSTEM.value(), "你是一个专业的会话摘要助手，请用简洁的中文总结以下对话要点，保留关键信息。"));
            messages.add(new ChatCompletionMessage(ChatMessageRole.USER.value(), prompt));
            // resolve model
            java.util.Optional<LLMModelEntity> modelEntityOpt = modelService.findByGlobalCode(model);
            LLMModelEntity modelEntity = modelEntityOpt.orElse(null);
            String providerKey = modelEntity != null ? modelEntity.getProvider() : model;
            Long modelId = modelEntity != null ? modelEntity.getId() : -1L;
            String requestId = java.util.UUID.randomUUID().toString();
            long start = System.currentTimeMillis();
            ChatCompletionResponse aiResponse = svc.chat(messages);
            String content = aiResponse.getChoices().get(0).getMessage().getContent();
            long latency = System.currentTimeMillis() - start;
            int pt = tokenEstimator.estimateTokens(prompt);
            int ct = tokenEstimator.estimateTokens(content);
            int total = pt + ct;
            Integer costCents = pricingService.calcCostCents(modelEntity, pt, ct);
            usageService.recordSuccess(null, requestId, null, modelId, providerKey,
                    modelEntity != null ? modelEntity.getCode() : providerKey,
                    pt, ct, total, latency, costCents);
            metricsService.recordSuccess(providerKey, null, modelEntity != null ? modelEntity.getCode() : providerKey, latency);
            return content;
        } catch (Exception e) {
            log.warn("summarize LLM failed, fallback", e);
            return fallbackSummarize(text);
        }

    public String summarizeUnread(java.util.Map<String, Object> vars) {
        try {
            String prompt = freeMarkEngineService.getContentByTemplate(PromptTemplateEnum.CHAT_UNREAD_SUMMARY.getPath(), vars);
            AbstractLLMChatService svc = LLMServiceFactory.getLLMService(model);
            java.util.List<ChatCompletionMessage> messages = new java.util.ArrayList<>();
            messages.add(new ChatCompletionMessage(ChatMessageRole.SYSTEM.value(), "你是一个专业的未读消息摘要助手，请用简洁的中文输出‘总览-会话要点-行动建议’三部分内容。"));
            messages.add(new ChatCompletionMessage(ChatMessageRole.USER.value(), prompt));
            java.util.Optional<LLMModelEntity> modelEntityOpt = modelService.findByGlobalCode(model);
            LLMModelEntity modelEntity = modelEntityOpt.orElse(null);
            String providerKey = modelEntity != null ? modelEntity.getProvider() : model;
            Long modelId = modelEntity != null ? modelEntity.getId() : -1L;
            String requestId = java.util.UUID.randomUUID().toString();
            long start = System.currentTimeMillis();
            ChatCompletionResponse aiResponse = svc.chat(messages);
            String content = aiResponse.getChoices().get(0).getMessage().getContent();
            long latency = System.currentTimeMillis() - start;
            int pt = tokenEstimator.estimateTokens(prompt);
            int ct = tokenEstimator.estimateTokens(content);
            int total = pt + ct;
            Integer costCents = pricingService.calcCostCents(modelEntity, pt, ct);
            usageService.recordSuccess(null, requestId, null, modelId, providerKey,
                    modelEntity != null ? modelEntity.getCode() : providerKey,
                    pt, ct, total, latency, costCents);
            metricsService.recordSuccess(providerKey, null, modelEntity != null ? modelEntity.getCode() : providerKey, latency);
            return content;
        } catch (Exception e) {
            log.warn("summarizeUnread LLM failed, fallback", e);
            return "暂无未读消息或生成失败";
        }
    }

    /**
     * 智能文章推荐（基于LLM分析文章相关性）
     */
    public String recommendArticles(Map<String, Object> vars) {
        try {
            String prompt = freeMarkEngineService.getContentByTemplate(PromptTemplateEnum.ARTICLE_RECOMMENDATION.getPath(), vars);
            AbstractLLMChatService svc = LLMServiceFactory.getLLMService(model);
            List<ChatCompletionMessage> messages = new ArrayList<>();
            messages.add(new ChatCompletionMessage(ChatMessageRole.SYSTEM.value(), "你是一个专业的文章推荐助手，分析文章与用户问题的相关性，返回JSON格式的推荐结果。"));
            messages.add(new ChatCompletionMessage(ChatMessageRole.USER.value(), prompt));
            java.util.Optional<LLMModelEntity> modelEntityOpt = modelService.findByGlobalCode(model);
            LLMModelEntity modelEntity = modelEntityOpt.orElse(null);
            String providerKey = modelEntity != null ? modelEntity.getProvider() : model;
            Long modelId = modelEntity != null ? modelEntity.getId() : -1L;
            String requestId = java.util.UUID.randomUUID().toString();
            long start = System.currentTimeMillis();
            ChatCompletionResponse aiResponse = svc.chat(messages);
            String content = aiResponse.getChoices().get(0).getMessage().getContent();
            long latency = System.currentTimeMillis() - start;
            int pt = tokenEstimator.estimateTokens(prompt);
            int ct = tokenEstimator.estimateTokens(content);
            int total = pt + ct;
            Integer costCents = pricingService.calcCostCents(modelEntity, pt, ct);
            usageService.recordSuccess(null, requestId, null, modelId, providerKey,
                    modelEntity != null ? modelEntity.getCode() : providerKey,
                    pt, ct, total, latency, costCents);
            metricsService.recordSuccess(providerKey, null, modelEntity != null ? modelEntity.getCode() : providerKey, latency);
            return content;
        } catch (Exception e) {
            log.warn("recommendArticles LLM failed, fallback", e);
            return "[]";
        }
    }

    public String generateTitle(String userMsg, String assistantMsg) {
        String seed = StringUtils.isNotBlank(userMsg) ? userMsg : assistantMsg;
        if (StringUtils.isBlank(seed)) return "新会话";
        try {
            Map<String, Object> vars = new HashMap<>();
            vars.put("content", seed);
            String prompt = freeMarkEngineService.getContentByTemplate(PromptTemplateEnum.TITLE_GENERATE.getPath(), vars);
            AbstractLLMChatService svc = LLMServiceFactory.getLLMService(model);
            List<ChatCompletionMessage> messages = new ArrayList<>();
            messages.add(new ChatCompletionMessage(ChatMessageRole.SYSTEM.value(), "你是一个标题生成助手，请基于内容生成不超过20个中文字符的简洁标题。"));
            messages.add(new ChatCompletionMessage(ChatMessageRole.USER.value(), prompt));
            java.util.Optional<LLMModelEntity> modelEntityOpt = modelService.findByGlobalCode(model);
            LLMModelEntity modelEntity = modelEntityOpt.orElse(null);
            String providerKey = modelEntity != null ? modelEntity.getProvider() : model;
            Long modelId = modelEntity != null ? modelEntity.getId() : -1L;
            String requestId = java.util.UUID.randomUUID().toString();
            long start = System.currentTimeMillis();
            ChatCompletionResponse aiResponse = svc.chat(messages);
            String title = aiResponse.getChoices().get(0).getMessage().getContent();
            long latency = System.currentTimeMillis() - start;
            int pt = tokenEstimator.estimateTokens(prompt);
            int ct = tokenEstimator.estimateTokens(title);
            int total = pt + ct;
            Integer costCents = pricingService.calcCostCents(modelEntity, pt, ct);
            usageService.recordSuccess(null, requestId, null, modelId, providerKey,
                    modelEntity != null ? modelEntity.getCode() : providerKey,
                    pt, ct, total, latency, costCents);
            metricsService.recordSuccess(providerKey, null, modelEntity != null ? modelEntity.getCode() : providerKey, latency);
            if (StringUtils.isBlank(title)) return simpleTitle(seed);
            title = title.replaceAll("\n", " ").trim();
            if (title.length() > 20) title = title.substring(0, 20);
            return title;
        } catch (Exception e) {
            log.warn("generateTitle LLM failed, fallback", e);
            return simpleTitle(seed);
        }
    }

    private String fallbackSummarize(String text) {
        if (text == null) return "";
        String t = text.trim();
        if (t.length() > 4000) t = t.substring(0, 4000);
        return t;
    }

    private String simpleTitle(String base) {
        base = base.replaceAll("\n", " ").trim();
        if (base.length() > 20) base = base.substring(0, 20) + "...";
        return base.isEmpty() ? "新会话" : base;
    }
}
